Pla Clima

El canvi climàtic és una realitat i està ocasionat per l’ésser humà. Ja tenim evidències dels seus impactes i cal actuar per a fer-hi front.

Les ciutats són especialment vulnerables, ja que concentren la majoria de la població mundial i és on l’energia es consumeix de manera més intensiva, generant el 70% de les emissions de gasos amb efecte d’hivernacle.

Barcelona és una ciutat mediterrània, que consumeix poca energia i genera poques emissions per càpita en relació a altres ciutats similars, però encara té molt camí per recórrer, ja que té una elevada dependència de recursos fòssils i nuclears.

Els efectes del canvi climàtic podrien presentar riscos en termes de salut i benestar de les persones (onades de calor), de seguretat (garantia de subministrament d’aigua i d’energia, vulnerabilitat de les infraestructures, risc d’incendis..) i en l’entorn natural que cal preveure i prevenir a nivell global.

Amb motiu de la celebració a París de la COP21, la 21a Conferència de les Parts de la Convenció Marc de les Nacions Unides sobre el Canvi Climàtic, i en el marc del Compromís Ciutadà per la Sostenibilitat, Barcelona va concretar un Compromís de Barcelona pel Clima, en què es comprometia a reduir les emissions de gasos em efecte hivernacle un 40% al 2030 en relació al 2005 i augmentar 1,6km2 de verd urbà com a mesura d’adaptació.

Ajuntament i ciutadania van establir un Full de Ruta 2015-2017 amb projectes municipals i ciutadans per aconseguir aquests objectius. A partir de l’experiència d’aquests dos anys l’Ajuntament vol donar una resposta més potent i estructurada a aquest compromís i per això es proposa aglutinar les accions que du a terme al voltant del repte del canvi climàtic en un únic pla que integri totes les línies de treball: el Pla Clima.

És un pla que alhora concreta els compromisos internacionals signats per l’Ajuntament, com és el Pacte d’Alcaldes i Alcaldesses pel Clima i l’Energia Sostenible.

Qualitat de l’aire de la ciutat de Barcelona

Es mostren dades dels contaminants mesurats a les estacions de la ciutat de Barcelona. L’actualització es realitza en intervals d’una hora indicant si el valor està o no validat i també es mostren les dades dels tres dies anteriors a l’actual. Tanmateix es publiquen històrics amb periodicitat mensual.

library(tidyverse)
── Attaching packages ──────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.1.0       ✔ purrr   0.3.1  
✔ tibble  2.1.3       ✔ dplyr   0.8.0.1
✔ tidyr   0.8.3       ✔ stringr 1.4.0  
✔ readr   1.3.1       ✔ forcats 0.3.0  
── Conflicts ─────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(data.table) 
data.table 1.12.0  Latest news: r-datatable.com

Attaching package: ‘data.table’

The following objects are masked from ‘package:dplyr’:

    between, first, last

The following object is masked from ‘package:purrr’:

    transpose
library(dplyr)
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:data.table’:

    hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year

The following object is masked from ‘package:base’:

    date
gener <- tbl_df(fread("data/2019_01_Gener_qualitat_aire_BCN.csv",
               header=TRUE))
gener %>% select(nom_cabina, longitud, latitud) %>% distinct()

rr gener2 <- gener %>% mutate(sector = as.factor(str_extract(nom_cabina, \(?<=[-]\\D).*\)), qualitat_aire = as.factor(qualitat_aire), qualitat_o3 = as.factor(qualitat_o3), valor_o3 = as.numeric(str_extract(valor_o3, ^[[:digit:]])), qualitat_no2 = as.factor(qualitat_no2), valor_no2 = as.numeric(str_extract(valor_no2, ^[[:digit:]])), qualitat_pm10 = as.factor(qualitat_pm10), valor_pm10 = as.numeric(str_extract(valor_pm10, ^[[:digit:]])), generat = dmy_hm(generat) ) %>% select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10, valor_pm10, generat) summary(gener2)

          sector     qualitat_aire  qualitat_o3     valor_o3      qualitat_no2 
 Ciutadella  : 738   --     : 162   --   : 287   Min.   :1.000   --     : 341  
 Eixample    : 738   Bona   :5571   Bona :4035   1st Qu.:2.000   Bona   :5358  
 Gràcia      : 738   Pobra  :   6   Pobra:   1   Median :4.000   Regular:  75  
 Observ Fabra: 738   Regular: 165   NA's :1581   Mean   :3.714   NA's   : 130  
 Palau Reial : 738                               3rd Qu.:5.000                 
 Poblenou    : 738                               Max.   :9.000                 
 (Other)     :1476                               NA's   :1868                  
   valor_no2     qualitat_pm10    valor_pm10       generat                   
 Min.   :1.000   --     :  42   Min.   :1.000   Min.   :2019-01-01 00:00:00  
 1st Qu.:2.000   Bona   :4238   1st Qu.:1.000   1st Qu.:2019-01-08 17:00:00  
 Median :3.000   Pobra  :   5   Median :1.000   Median :2019-01-16 14:30:00  
 Mean   :3.654   Regular: 102   Mean   :2.447   Mean   :2019-01-16 12:34:13  
 3rd Qu.:5.000   NA's   :1517   3rd Qu.:2.000   3rd Qu.:2019-01-24 07:00:00  
 Max.   :9.000                  Max.   :9.000   Max.   :2019-01-31 23:00:00  
 NA's   :471                    NA's   :1559                                 

rr gener2 %>% filter(sector == Reial) %>% select(valor_no2, generat) %>% ggplot(aes(x = generat, y = valor_no2)) + geom_line()

rr gener2 %>% filter(sector == Reial, generat >= as.Date(019-01-15), generat <= as.Date(019-01-16)) %>% select(valor_no2, generat) %>% ggplot(aes(x = generat, y = valor_no2)) + geom_line() + geom_point()

rr NA

gener3 <- gener %>% 
  mutate(sector = as.factor(str_extract(nom_cabina, "(?<=[-]\\D).*")),
         qualitat_aire = as.factor(qualitat_aire),
         qualitat_o3 = as.factor(qualitat_o3),
         valor_o3 = as.numeric(str_extract(valor_o3, "^[[:digit:]]")),
         qualitat_no2 = as.factor(qualitat_no2),
         valor_no2 = as.numeric(str_extract(valor_no2, "^[[:digit:]]")),
         qualitat_pm10 = as.factor(qualitat_pm10),
         valor_pm10 = as.numeric(str_extract(valor_pm10, "^[[:digit:]]")),
         date = str_extract(generat, ".*[[:space:]]"),
         hour = str_extract(generat, "(?<=[[:space:]])[0-9.]+")) %>%
  separate(col = date, into = c("day", "month", "year"), sep = "/") %>%
  mutate(day = as.integer(day),
         month = as.integer(month),
         year = as.integer(year),
         hour = as.integer(hour)) %>%
  select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10,
         valor_pm10, day, month, year, hour)
Error in eval(lhs, parent, parent) : objeto 'gener' no encontrado

BV: µg/m³ medio de contaminadores por horas en enero en 8 barrios de Barcelona.

gener3 %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year == 2019, month == 1) %>%
  select(day, hour, measure, measure_value, sector) %>%
  group_by(hour, measure, sector) %>%
  summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(hour, mean_val_hour, color = measure)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Hora", 
       y = "µg/m³ medio",
       color = "Contaminador",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line() +
  #geom_point() + 
  facet_wrap(~ sector, nrow = 2) +
  theme_minimal()
Error in eval(lhs, parent, parent) : objeto 'gener3' no encontrado

The study suggested that for 2015, the total existing UK vegetation reduces the average annual surface concentration by about 10% for PM2.5, 6% for PM10, 13% for O3, 24% for NH3 and 30% for SO2, but did not markedly change NO2 concentrations. https://airqualitynews.com/2018/07/30/plants-and-trees-not-the-solution-to-air-pollution-in-cities/

Cleaning dataset function:

clean_bcn_data <- function(data) {
  data <- data %>% 
  mutate(sector = as.factor(str_extract(nom_cabina, "(?<=[-]\\D).*")),
         qualitat_aire = as.factor(qualitat_aire),
         qualitat_o3 = as.factor(qualitat_o3),
         valor_o3 = as.numeric(str_extract(valor_o3, "^[[:digit:]]")),
         qualitat_no2 = as.factor(qualitat_no2),
         valor_no2 = as.numeric(str_extract(valor_no2, "^[[:digit:]]")),
         qualitat_pm10 = as.factor(qualitat_pm10),
         valor_pm10 = as.numeric(str_extract(valor_pm10, "^[[:digit:]]")),
         date = str_extract(generat, ".*[[:space:]]"),
         hour = str_extract(generat, "(?<=[[:space:]])[0-9.]+")) %>%
  separate(col = date, into = c("day", "month", "year"), sep = "/") %>%
  mutate(day = as.integer(day),
         month = as.integer(month),
         year = as.integer(year),
         hour = as.integer(hour),
         #sector = case_when(sector == "Ciutadella" ~ as.factor("Ciutat Vella"), TRUE ~ as.factor(sector)),
         month = case_when(month == 1 ~ as.integer(13), TRUE ~ as.integer(month))) %>%
  select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10,
         valor_pm10, day, month, year, hour)
  data
}

Aggregate data:

data_06_2018 <- tbl_df(fread("data/2018_06_Juny_qualitat_aire_BCN.csv", header=TRUE))
data_07_2018 <- tbl_df(fread("data/2018_07_Juliol_qualitat_aire_BCN.csv", header=TRUE))
data_08_2018 <- tbl_df(fread("data/2018_08_Agost_qualitat_aire_BCN.csv", header=TRUE))
data_09_2018 <- tbl_df(fread("data/2018_09_Setembre_qualitat_aire_BCN.csv", header=TRUE))
data_10_2018 <- tbl_df(fread("data/2018_10_Octubre_qualitat_aire_BCN.csv", header=TRUE))
data_12_2018 <- tbl_df(fread("data/2018_12_Desembre_qualitat_aire_BCN.csv", header=TRUE))
data_11_2018 <- tbl_df(fread("data/2018_11_novembre_qualitat_aire_BCN.csv", header=TRUE))
data_01_2019 <- tbl_df(fread("data/2019_01_Gener_qualitat_aire_BCN.csv", header=TRUE))
data <- rbind(data_06_2018,
              data_07_2018,
              data_08_2018,
              data_09_2018,
              data_10_2018,
              data_11_2018,
              data_12_2018,
              data_01_2019) %>% clean_bcn_data() 
summary(data)
         sector     qualitat_aire    qualitat_o3       valor_o3      qualitat_no2     valor_no2    
 Ciutadella :5320   --     : 2573   --     : 1893   Min.   :1.000   --     : 2302   Min.   :1.000  
 Eixample   :5320   Bona   :36760   Bona   :27028   1st Qu.:2.000   Bona   :36990   1st Qu.:2.000  
 Gràcia     :5320   Pobra  :  160   Pobra  :   18   Median :4.000   Regular:  595   Median :3.000  
 Palau Reial:5320   Regular: 2394   Regular:  541   Mean   :4.196   NA's   : 2000   Mean   :3.548  
 Poblenou   :5320                   NA's   :12407   3rd Qu.:6.000                   3rd Qu.:5.000  
 Sants      :5320                                   Max.   :9.000                   Max.   :9.000  
 (Other)    :9967                                   NA's   :14309                   NA's   :4311   
 qualitat_pm10     valor_pm10         day            month             year           hour     
 --     :  542   Min.   :1.000   Min.   : 1.00   Min.   : 6.000   Min.   :2018   Min.   : 0.0  
 Bona   :23621   1st Qu.:1.000   1st Qu.: 9.00   1st Qu.: 8.000   1st Qu.:2018   1st Qu.: 6.0  
 Pobra  :  142   Median :2.000   Median :16.00   Median :10.000   Median :2018   Median :12.0  
 Regular: 1393   Mean   :2.316   Mean   :16.34   Mean   : 9.847   Mean   :2018   Mean   :11.6  
 NA's   :16189   3rd Qu.:3.000   3rd Qu.:24.00   3rd Qu.:12.000   3rd Qu.:2018   3rd Qu.:18.0  
                 Max.   :9.000   Max.   :31.00   Max.   :13.000   Max.   :2019   Max.   :23.0  
                 NA's   :16740                                                                 
plotit <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, hour, measure, sector) %>%
  summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(hour, mean_val_hour, color = measure)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Hora", 
       y = "µg/m³ medio",
       color = "Contaminador",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line() +
  geom_point() + 
  facet_grid(sector ~ month) +
  theme_minimal()
(j <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  #filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  filter(year >= 2018, month >= 6) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
   mutate(measure = case_when(measure == "valor_no2" ~ "NO2",
                              measure == "valor_o3" ~ "O3",
                              measure == "valor_pm10" ~ "PM10",
                              TRUE ~ measure)) %>%
  group_by(month, measure, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month)) +
  labs(title = "Monthly average of pollutants colored by district, June 2018 - Jan 2019",
       x = "Month", 
       y = "µg/m³",
       color = "District",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1, aes(color = sector)) +
  geom_smooth(se=FALSE, color="black", linetype = "dashed", method=lm) +
  #geom_point() + 
  facet_wrap(~ measure, ncol = 3) +
  scale_colour_manual(values = c("#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#999999","#a65628","#f781bf")) +
  theme_mine())

#method=lm for geom_smooth
ggplotly(j) 
Removed 36 rows containing non-finite values (stat_smooth).
saveWidget(ggplotly(j, dynamicTicks = TRUE), file = "meanbymonth2018.html")
Removed 36 rows containing non-finite values (stat_smooth).
data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  #filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  filter(year >= 2018, month >= 6) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, measure, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month, color = measure)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Mes", 
       y = "µg/m³ medio",
       color = "Contaminador",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1) +
  #geom_point() + 
  facet_wrap(~ sector, ncol = 4) +
  theme_mine()

(plotit <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Mes", 
       y = "µg/m³ medio",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  geom_line() +
  geom_point() + 
  facet_wrap(~ sector, nrow = 4) +
  theme_mine())

library(plotly)

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(htmlwidgets)
#saveWidget(ggplotly(plotit, dynamicTicks = FALSE), file = "meancont.html");

Just clean

clean_data <- function(data) {
  data <- data %>% 
  mutate(sector = as.factor(str_extract(nom_cabina, "(?<=[-]\\D).*")),
         qualitat_aire = as.factor(qualitat_aire),
         qualitat_o3 = as.factor(qualitat_o3),
         valor_o3 = as.numeric(str_extract(valor_o3, "^[[:digit:]]")),
         qualitat_no2 = as.factor(qualitat_no2),
         valor_no2 = as.numeric(str_extract(valor_no2, "^[[:digit:]]")),
         qualitat_pm10 = as.factor(qualitat_pm10),
         valor_pm10 = as.numeric(str_extract(valor_pm10, "^[[:digit:]]")),
         date = str_extract(generat, ".*[[:space:]]"),
         hour = str_extract(generat, "(?<=[[:space:]])[0-9.]+")) %>%
  separate(col = date, into = c("day", "month", "year"), sep = "/") %>%
  mutate(day = as.integer(day),
         month = as.integer(month),
         year = as.integer(year),
         hour = as.integer(hour),
         month = as.integer(month)) %>%
  select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10,
         valor_pm10, day, month, year, hour)
  data
}
(p <- data_04_2019 %>% clean_data() %>%
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year == 2019, month == 4) %>%
  select(day, hour, measure, measure_value, sector) %>%
   mutate(measure = case_when(measure == "valor_no2" ~ "NO2",
                              measure == "valor_o3" ~ "O3",
                              measure == "valor_pm10" ~ "PM10",
                              TRUE ~ measure)) %>%
  group_by(hour, measure, sector) %>%
  summarise(avg_hour = as.numeric(format(round(mean(measure_value, na.rm = TRUE), digits = 2), nsmall = 2))) %>%
   
   
   
  ggplot(aes(hour, avg_hour, color = measure)) +
  labs(title = "Mean value of pollutants by hour in April 2019",
       x = "Hour", 
       y = "µg/m³",
       color = "Pollutant",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1) +
  #geom_point() + 
  facet_wrap(~ sector, nrow = 2) +
  scale_colour_manual(values = c("#e41a1c","#377eb8","#4daf4a")) +
  theme_mine()
  )
Error in stri_extract_first_regex(string, pattern, opts_regex = opts(pattern)) : 
  objeto 'nom_cabina' no encontrado
saveWidget(ggplotly(p, dynamicTicks = TRUE), file = "meanjan.html")
ggplotly(p) 

Mortalitat

mortalitat <- tbl_df(fread("2018_taxa_mortalitat.csv", header=TRUE))
Error in fread("2018_taxa_mortalitat.csv", header = TRUE) : 
  File '2018_taxa_mortalitat.csv' does not exist or is non-readable. getwd()=='/Users/3omni/Documents/GitHub/bcn-contamination-dataviz'
theme_mine <- function () { 
    theme_bw(base_size=12, base_family="Helvetica") %+replace% 
        theme(
            panel.background  = element_blank(),
            plot.background = element_rect(fill="transparent", colour=NA), 
            legend.background = element_rect(fill="transparent", colour=NA),
            legend.key = element_rect(fill="transparent", colour=NA)
        )
}
data_06_2019 <- tbl_df(fread("data/2019_06_juny_qualitat_aire_BCN.csv", header=TRUE))
data_04_2019 <- tbl_df(fread("data/2019_04_Abril_qualitat_aire_BCN.csv", header=TRUE))
#summary(data_06_2019)
length(names(data_06_2019))
[1] 57
(i <- data_06_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value) %>%
  #filter(sector == "Ciutadella") %>%
  group_by(hour, measure, sector) %>%
  summarise(avg_hour = as.numeric(format(round(mean(measure_value, na.rm = TRUE), digits = 2), nsmall = 2))) %>%
    
  ggplot(aes(hour, avg_hour, color = measure)) +
  labs(title = "Mean value of pollutants by hour in June 2019",
       x = "Hour", 
       y = "µg/m³",
       color = "Pollutant",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  #scale_color_manual(values = c("purple", "yellow", "red", "orange", "green", "blue", "pink")) +
  geom_line(size=1) +
  #geom_hline(yintercept = 90, linetype = 2, color = "red") +
  #geom_hline(yintercept = 110, linetype = 2, color = "green") +
  #geom_hline(yintercept = 200, linetype = 2, color = "pink") +
  #geom_text(aes(0,90,label = "Limit NO2 by h", vjust = -1), color = "black") +
  #geom_point() + 
  scale_x_continuous(limits = c(0, 22)) + 
  facet_wrap(~ sector, nrow = 1) +
    scale_colour_manual(values = c("#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#999999","#a65628")) +
  theme_mine())

NA
ggplotly(i) 
saveWidget(ggplotly(i, dynamicTicks = TRUE), file = "meanjun19.html")
april19 <- data_04_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value)
june19 <- data_06_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value)
data19 <- rbind(april19, june19)
summary(data19)
         sector            year          month            day       
 Ciutadella :135936   Min.   :2019   Min.   :4.000   Min.   : 1.00  
 Eixample   :237888   1st Qu.:2019   1st Qu.:4.000   1st Qu.: 8.00  
 Gràcia     :237888   Median :2019   Median :6.000   Median :16.00  
 Palau Reial:237888   Mean   :2019   Mean   :5.014   Mean   :15.75  
 Poblenou   :132480   3rd Qu.:2019   3rd Qu.:6.000   3rd Qu.:23.00  
 Sants      :101952   Max.   :2019   Max.   :6.000   Max.   :30.00  
 Vall Hebron:237888                                                 
      hour       measure       measure_value   
 Min.   : 1.00   CO  :135936   Min.   :  0.20  
 1st Qu.: 6.75   NO  :237888   1st Qu.:  2.00  
 Median :12.50   NO2 :237888   Median : 17.00  
 Mean   :12.50   NOx :237888   Mean   : 27.36  
 3rd Qu.:18.25   O3  :169920   3rd Qu.: 41.00  
 Max.   :24.00   PM10:166464   Max.   :759.00  
                 SO2 :135936   NA's   :44856   
(k <- data19 %>% 
  filter(year >= 2019, month >= 4) %>%
  group_by(month, measure, sector) %>%
  summarise(avg_month = as.numeric(format(round(mean(measure_value, na.rm = TRUE), digits = 2), nsmall = 2))) %>%
  #select(month, day, hour, measure, measure_value, sector) %>%
  ggplot(aes(month, avg_month)) +
  labs(title = "Monthly average of pollutants colored by district, April 2019 - June 2019",
       x = "Month", 
       y = "µg/m³",
       color = "District",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1, aes(color = sector)) +
  #geom_smooth(se=FALSE, color="black", linetype = "dashed", method=lm) +
  #geom_point() + 
  scale_x_continuous(breaks = c(4,6)) +
  facet_wrap(~ measure, ncol = 7) +
   scale_colour_manual(values = c("#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#999999","#a65628")) +
  theme_mine())

#method=lm for geom_smooth
ggplotly(k) 
saveWidget(ggplotly(k, dynamicTicks = TRUE), file = "mean19.html")
accidents18 <- tbl_df(fread("data/2018_accidents_causes_gu_bcn.csv",header=TRUE))
summary(accidents18)
 Numero_expedient   Codi_districte   Nom_districte        Codi_barri  Nom_barri        
 Length:9926        Min.   :-1.000   Length:9926        Min.   :-1   Length:9926       
 Class :character   1st Qu.: 2.000   Class :character   1st Qu.: 8   Class :character  
 Mode  :character   Median : 4.000   Mode  :character   Median :20   Mode  :character  
                    Mean   : 4.834                      Mean   :27                     
                    3rd Qu.: 7.000                      3rd Qu.:43                     
                    Max.   :10.000                      Max.   :73                     
  Codi_carrer      Nom_carrer         Num_postal        Descripcio_dia_setmana
 Min.   :    -1   Length:9926        Length:9926        Length:9926           
 1st Qu.:119003   Class :character   Class :character   Class :character      
 Median :191204   Mode  :character   Mode  :character   Mode  :character      
 Mean   :250401                                                               
 3rd Qu.:320908                                                               
 Max.   :701857                                                               
 Dia_setmana        Descripcio_tipus_dia      Any          Mes_any         Nom_mes         
 Length:9926        Length:9926          Min.   :2018   Min.   : 1.000   Length:9926       
 Class :character   Class :character     1st Qu.:2018   1st Qu.: 4.000   Class :character  
 Mode  :character   Mode  :character     Median :2018   Median : 6.000   Mode  :character  
                                         Mean   :2018   Mean   : 6.484                     
                                         3rd Qu.:2018   3rd Qu.:10.000                     
                                         Max.   :2018   Max.   :12.000                     
    Dia_mes         Hora_dia     Descripcio_torn    Descripcio_causa_mediata Coordenada_UTM_X
 Min.   : 1.00   Min.   : 0.00   Length:9926        Length:9926              Min.   :424027  
 1st Qu.: 8.00   1st Qu.:10.00   Class :character   Class :character         1st Qu.:428659  
 Median :16.00   Median :14.00   Mode  :character   Mode  :character         Median :430202  
 Mean   :15.66   Mean   :13.83                                               Mean   :430124  
 3rd Qu.:23.00   3rd Qu.:18.00                                               3rd Qu.:431564  
 Max.   :31.00   Max.   :23.00                                               Max.   :435086  
 Coordenada_UTM_Y     Longitud           Latitud        
 Min.   :4575229   Min.   :   2.090   Min.   :   41.32  
 1st Qu.:4582171   1st Qu.:   2.146   1st Qu.:   41.39  
 Median :4583422   Median :   2.164   Median :   41.40  
 Mean   :4583697   Mean   :   3.685   Mean   :   87.22  
 3rd Qu.:4584969   3rd Qu.:   2.180   3rd Qu.:   41.41  
 Max.   :4590759   Max.   :2188.000   Max.   :41414.00  
head(accidents18)
(ac<- accidents18 %>% filter(Mes_any >= 6, Any == 2018) %>%
  mutate(sector = case_when(Nom_districte == "Desconegut" ~ as.character(NA),TRUE ~ as.character(Nom_districte)),
         sector = as.factor(sector),
         year = Any,
         month = Mes_any,
         day = Dia_mes,
         hour = Hora_dia) %>%
   drop_na() %>%
  select(sector, year, month, day, hour))
levels(ac$sector)
 [1] "Ciutat Vella"        "Eixample"            "Gràcia"              "Horta-Guinardó"     
 [5] "Les Corts"           "Nou Barris"          "Sant Andreu"         "Sant Martí"         
 [9] "Sants-Montjuïc"      "Sarrià-Sant Gervasi"
ac %>%
  group_by(sector, month, hour) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = hour, y = incidents, color = factor(month))) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
ac %>%
  group_by(sector, hour) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = hour, y = incidents, color = sector)) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  #facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
ac %>%
  group_by(sector, month) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = month, y = incidents, color = sector)) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  #facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
LS0tCnRpdGxlOiAiT3BlbiBEYXRhIEJhcmNlbG9uYSIKYXV0aG9yOiAiUml0YSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIyMgUGxhIENsaW1hCgpFbCBjYW52aSBjbGltw6B0aWMgw6lzIHVuYSByZWFsaXRhdCBpIGVzdMOgIG9jYXNpb25hdCBwZXIgbOKAmcOpc3NlciBodW3DoC4gSmEgdGVuaW0gZXZpZMOobmNpZXMgZGVscyBzZXVzIGltcGFjdGVzIGkgY2FsIGFjdHVhciBwZXIgYSBmZXItaGkgZnJvbnQuICAKCkxlcyBjaXV0YXRzIHPDs24gZXNwZWNpYWxtZW50IHZ1bG5lcmFibGVzLCBqYSBxdWUgY29uY2VudHJlbiBsYSBtYWpvcmlhIGRlIGxhIHBvYmxhY2nDsyBtdW5kaWFsIGkgw6lzIG9uIGzigJllbmVyZ2lhIGVzIGNvbnN1bWVpeCBkZSBtYW5lcmEgbcOpcyBpbnRlbnNpdmEsIGdlbmVyYW50IGVsIDcwJSBkZSBsZXMgZW1pc3Npb25zIGRlIGdhc29zIGFtYiBlZmVjdGUgZOKAmWhpdmVybmFjbGUuCgpCYXJjZWxvbmEgw6lzIHVuYSBjaXV0YXQgbWVkaXRlcnLDoG5pYSwgcXVlIGNvbnN1bWVpeCBwb2NhIGVuZXJnaWEgaSBnZW5lcmEgcG9xdWVzIGVtaXNzaW9ucyBwZXIgY8OgcGl0YSBlbiByZWxhY2nDsyBhIGFsdHJlcyBjaXV0YXRzIHNpbWlsYXJzLCBwZXLDsiBlbmNhcmEgdMOpIG1vbHQgY2Ftw60gcGVyIHJlY8OzcnJlciwgamEgcXVlIHTDqSB1bmEgZWxldmFkYSBkZXBlbmTDqG5jaWEgZGUgcmVjdXJzb3MgZsOyc3NpbHMgaSBudWNsZWFycy4KCkVscyBlZmVjdGVzIGRlbCBjYW52aSBjbGltw6B0aWMgcG9kcmllbiBwcmVzZW50YXIgcmlzY29zIGVuIHRlcm1lcyBkZSBzYWx1dCBpIGJlbmVzdGFyIGRlIGxlcyBwZXJzb25lcyAob25hZGVzIGRlIGNhbG9yKSwgZGUgc2VndXJldGF0IChnYXJhbnRpYSBkZSBzdWJtaW5pc3RyYW1lbnQgZOKAmWFpZ3VhIGkgZOKAmWVuZXJnaWEsIHZ1bG5lcmFiaWxpdGF0IGRlIGxlcyBpbmZyYWVzdHJ1Y3R1cmVzLCByaXNjIGTigJlpbmNlbmRpcy4uKSBpIGVuIGzigJllbnRvcm4gbmF0dXJhbCBxdWUgY2FsIHByZXZldXJlIGkgcHJldmVuaXIgYSBuaXZlbGwgZ2xvYmFsLgoKQW1iIG1vdGl1IGRlIGxhIGNlbGVicmFjacOzIGEgUGFyw61zIGRlIGxhIENPUDIxLCBsYSAyMWEgQ29uZmVyw6huY2lhIGRlIGxlcyBQYXJ0cyBkZSBsYSBDb252ZW5jacOzIE1hcmMgZGUgbGVzIE5hY2lvbnMgVW5pZGVzIHNvYnJlIGVsIENhbnZpIENsaW3DoHRpYywgaSBlbiBlbCBtYXJjIGRlbCBDb21wcm9tw61zIENpdXRhZMOgIHBlciBsYSBTb3N0ZW5pYmlsaXRhdCwgQmFyY2Vsb25hIHZhIGNvbmNyZXRhciB1biBDb21wcm9tw61zIGRlIEJhcmNlbG9uYSBwZWwgQ2xpbWEsIGVuIHF1w6ggZXMgY29tcHJvbWV0aWEgYSByZWR1aXIgbGVzIGVtaXNzaW9ucyBkZSBnYXNvcyBlbSBlZmVjdGUgaGl2ZXJuYWNsZSB1biA0MCUgYWwgMjAzMCBlbiByZWxhY2nDsyBhbCAyMDA1IGkgYXVnbWVudGFyIDEsNmttMiBkZSB2ZXJkIHVyYsOgIGNvbSBhIG1lc3VyYSBk4oCZYWRhcHRhY2nDsy4KCkFqdW50YW1lbnQgaSBjaXV0YWRhbmlhIHZhbiBlc3RhYmxpciB1biBGdWxsIGRlIFJ1dGEgMjAxNS0yMDE3IGFtYiBwcm9qZWN0ZXMgbXVuaWNpcGFscyBpIGNpdXRhZGFucyBwZXIgYWNvbnNlZ3VpciBhcXVlc3RzIG9iamVjdGl1cy4gQSBwYXJ0aXIgZGUgbOKAmWV4cGVyacOobmNpYSBk4oCZYXF1ZXN0cyBkb3MgYW55cyBs4oCZQWp1bnRhbWVudCB2b2wgZG9uYXIgdW5hIHJlc3Bvc3RhIG3DqXMgcG90ZW50IGkgZXN0cnVjdHVyYWRhIGEgYXF1ZXN0IGNvbXByb23DrXMgaSBwZXIgYWl4w7IgZXMgcHJvcG9zYSBhZ2x1dGluYXIgbGVzIGFjY2lvbnMgcXVlIGR1IGEgdGVybWUgYWwgdm9sdGFudCBkZWwgcmVwdGUgZGVsIGNhbnZpIGNsaW3DoHRpYyBlbiB1biDDum5pYyBwbGEgcXVlIGludGVncmkgdG90ZXMgbGVzIGzDrW5pZXMgZGUgdHJlYmFsbDogZWwgUGxhIENsaW1hLgoKw4lzIHVuIHBsYSBxdWUgYWxob3JhIGNvbmNyZXRhIGVscyBjb21wcm9taXNvcyBpbnRlcm5hY2lvbmFscyBzaWduYXRzIHBlciBs4oCZQWp1bnRhbWVudCwgY29tIMOpcyBlbCBQYWN0ZSBk4oCZQWxjYWxkZXMgaSBBbGNhbGRlc3NlcyBwZWwgQ2xpbWEgaSBs4oCZRW5lcmdpYSBTb3N0ZW5pYmxlLgoKIyMgUXVhbGl0YXQgZGUgbCdhaXJlIGRlIGxhIGNpdXRhdCBkZSBCYXJjZWxvbmEKRXMgbW9zdHJlbiBkYWRlcyBkZWxzIGNvbnRhbWluYW50cyBtZXN1cmF0cyBhIGxlcyBlc3RhY2lvbnMgZGUgbGEgY2l1dGF0IGRlIEJhcmNlbG9uYS4KTCdhY3R1YWxpdHphY2nDsyBlcyByZWFsaXR6YSBlbiBpbnRlcnZhbHMgZCd1bmEgaG9yYSBpbmRpY2FudCBzaSBlbCB2YWxvciBlc3TDoCBvIG5vIHZhbGlkYXQgaSB0YW1iw6kgZXMgbW9zdHJlbiBsZXMgZGFkZXMgZGVscyB0cmVzIGRpZXMgYW50ZXJpb3JzIGEgbCdhY3R1YWwuIFRhbm1hdGVpeCBlcyBwdWJsaXF1ZW4gaGlzdMOycmljcyBhbWIgcGVyaW9kaWNpdGF0IG1lbnN1YWwuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZGF0YS50YWJsZSkgCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCmBgYHtyfQpnZW5lciA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOV8wMV9HZW5lcl9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLAogICAgICAgICAgICAgICBoZWFkZXI9VFJVRSkpCmdlbmVyICU+JSBzZWxlY3Qobm9tX2NhYmluYSwgbG9uZ2l0dWQsIGxhdGl0dWQpICU+JSBkaXN0aW5jdCgpCmBgYAoKYGBge3J9CmdlbmVyMiA8LSBnZW5lciAlPiUKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKHN0cl9leHRyYWN0KG5vbV9jYWJpbmEsICIoPzw9Wy1dXFxEKS4qIikpLAogICAgICAgICBxdWFsaXRhdF9haXJlID0gYXMuZmFjdG9yKHF1YWxpdGF0X2FpcmUpLAogICAgICAgICBxdWFsaXRhdF9vMyA9IGFzLmZhY3RvcihxdWFsaXRhdF9vMyksCiAgICAgICAgIHZhbG9yX28zID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9vMywgIl5bWzpkaWdpdDpdXSIpKSwKICAgICAgICAgcXVhbGl0YXRfbm8yID0gYXMuZmFjdG9yKHF1YWxpdGF0X25vMiksCiAgICAgICAgIHZhbG9yX25vMiA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodmFsb3Jfbm8yLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9wbTEwID0gYXMuZmFjdG9yKHF1YWxpdGF0X3BtMTApLAogICAgICAgICB2YWxvcl9wbTEwID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9wbTEwLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBnZW5lcmF0ID0gZG15X2htKGdlbmVyYXQpCiAgICAgICAgICkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZ2VuZXJhdCkKc3VtbWFyeShnZW5lcjIpCmBgYAoKYGBge3J9CmdlbmVyMiAlPiUgCiAgZmlsdGVyKHNlY3RvciA9PSAiUGFsYXUgUmVpYWwiKSAlPiUgCiAgc2VsZWN0KHZhbG9yX25vMiwgZ2VuZXJhdCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2VuZXJhdCwgeSA9IHZhbG9yX25vMikpICsKICBnZW9tX2xpbmUoKQoKYGBgCgpgYGB7cn0KZ2VuZXIyICU+JSAKICBmaWx0ZXIoc2VjdG9yID09ICJQYWxhdSBSZWlhbCIsIGdlbmVyYXQgPj0gYXMuRGF0ZSgiMjAxOS0wMS0xNSIpLCBnZW5lcmF0IDw9IGFzLkRhdGUoIjIwMTktMDEtMTYiKSkgJT4lIAogIHNlbGVjdCh2YWxvcl9ubzIsIGdlbmVyYXQpICU+JQogIGdncGxvdChhZXMoeCA9IGdlbmVyYXQsIHkgPSB2YWxvcl9ubzIpKSArCiAgZ2VvbV9saW5lKCkgKyBnZW9tX3BvaW50KCkKICAKCmBgYAoKCmBgYHtyfQpnZW5lcjMgPC0gZ2VuZXIgJT4lIAogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3Ioc3RyX2V4dHJhY3Qobm9tX2NhYmluYSwgIig/PD1bLV1cXEQpLioiKSksCiAgICAgICAgIHF1YWxpdGF0X2FpcmUgPSBhcy5mYWN0b3IocXVhbGl0YXRfYWlyZSksCiAgICAgICAgIHF1YWxpdGF0X28zID0gYXMuZmFjdG9yKHF1YWxpdGF0X28zKSwKICAgICAgICAgdmFsb3JfbzMgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX28zLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9ubzIgPSBhcy5mYWN0b3IocXVhbGl0YXRfbm8yKSwKICAgICAgICAgdmFsb3Jfbm8yID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9ubzIsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIHF1YWxpdGF0X3BtMTAgPSBhcy5mYWN0b3IocXVhbGl0YXRfcG0xMCksCiAgICAgICAgIHZhbG9yX3BtMTAgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX3BtMTAsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIGRhdGUgPSBzdHJfZXh0cmFjdChnZW5lcmF0LCAiLipbWzpzcGFjZTpdXSIpLAogICAgICAgICBob3VyID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIig/PD1bWzpzcGFjZTpdXSlbMC05Ll0rIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGRhdGUsIGludG8gPSBjKCJkYXkiLCAibW9udGgiLCAieWVhciIpLCBzZXAgPSAiLyIpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKGRheSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihtb250aCksCiAgICAgICAgIHllYXIgPSBhcy5pbnRlZ2VyKHllYXIpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihob3VyKSkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZGF5LCBtb250aCwgeWVhciwgaG91cikKc3VtbWFyeShnZW5lcjMpCmBgYAoKQlY6IMK1Zy9twrMgbWVkaW8gZGUgY29udGFtaW5hZG9yZXMgcG9yIGhvcmFzIGVuIGVuZXJvIGVuIDggYmFycmlvcyBkZSBCYXJjZWxvbmEuCmBgYHtyfQpnZW5lcjMgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDE5LCBtb250aCA9PSAxKSAlPiUKICBzZWxlY3QoZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogIGdyb3VwX2J5KGhvdXIsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKG1lYW5fdmFsX2hvdXIgPSBtZWFuKG1lYXN1cmVfdmFsdWUsIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMoaG91ciwgbWVhbl92YWxfaG91ciwgY29sb3IgPSBtZWFzdXJlKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIkhvcmEiLCAKICAgICAgIHkgPSAiwrVnL23CsyBtZWRpbyIsCiAgICAgICBjb2xvciA9ICJDb250YW1pbmFkb3IiLAogICAgICAgY2FwdGlvbiA9ICJEYXRvcyBkZSBvcGVuZGF0YS1hanVudGFtZW50LmJhcmNlbG9uYS5jYXQiKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogIGdlb21fbGluZSgpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbnJvdyA9IDIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpUaGUgc3R1ZHkgc3VnZ2VzdGVkIHRoYXQgZm9yIDIwMTUsIHRoZSB0b3RhbCBleGlzdGluZyBVSyB2ZWdldGF0aW9uIHJlZHVjZXMgdGhlIGF2ZXJhZ2UgYW5udWFsIHN1cmZhY2UgY29uY2VudHJhdGlvbiBieSBhYm91dCAxMCUgZm9yIFBNMi41LCA2JSBmb3IgUE0xMCwgMTMlIGZvciBPMywgMjQlIGZvciBOSDMgYW5kIDMwJSBmb3IgU08yLCBidXQgZGlkIG5vdCBtYXJrZWRseSBjaGFuZ2UgTk8yIGNvbmNlbnRyYXRpb25zLgpodHRwczovL2FpcnF1YWxpdHluZXdzLmNvbS8yMDE4LzA3LzMwL3BsYW50cy1hbmQtdHJlZXMtbm90LXRoZS1zb2x1dGlvbi10by1haXItcG9sbHV0aW9uLWluLWNpdGllcy8KCkNsZWFuaW5nIGRhdGFzZXQgZnVuY3Rpb246CmBgYHtyfQpjbGVhbl9iY25fZGF0YSA8LSBmdW5jdGlvbihkYXRhKSB7CiAgZGF0YSA8LSBkYXRhICU+JSAKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKHN0cl9leHRyYWN0KG5vbV9jYWJpbmEsICIoPzw9Wy1dXFxEKS4qIikpLAogICAgICAgICBxdWFsaXRhdF9haXJlID0gYXMuZmFjdG9yKHF1YWxpdGF0X2FpcmUpLAogICAgICAgICBxdWFsaXRhdF9vMyA9IGFzLmZhY3RvcihxdWFsaXRhdF9vMyksCiAgICAgICAgIHZhbG9yX28zID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9vMywgIl5bWzpkaWdpdDpdXSIpKSwKICAgICAgICAgcXVhbGl0YXRfbm8yID0gYXMuZmFjdG9yKHF1YWxpdGF0X25vMiksCiAgICAgICAgIHZhbG9yX25vMiA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodmFsb3Jfbm8yLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9wbTEwID0gYXMuZmFjdG9yKHF1YWxpdGF0X3BtMTApLAogICAgICAgICB2YWxvcl9wbTEwID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9wbTEwLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBkYXRlID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIi4qW1s6c3BhY2U6XV0iKSwKICAgICAgICAgaG91ciA9IHN0cl9leHRyYWN0KGdlbmVyYXQsICIoPzw9W1s6c3BhY2U6XV0pWzAtOS5dKyIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBkYXRlLCBpbnRvID0gYygiZGF5IiwgIm1vbnRoIiwgInllYXIiKSwgc2VwID0gIi8iKSAlPiUKICBtdXRhdGUoZGF5ID0gYXMuaW50ZWdlcihkYXkpLAogICAgICAgICBtb250aCA9IGFzLmludGVnZXIobW9udGgpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICAgICAgICAgaG91ciA9IGFzLmludGVnZXIoaG91ciksCiAgICAgICAgICNzZWN0b3IgPSBjYXNlX3doZW4oc2VjdG9yID09ICJDaXV0YWRlbGxhIiB+IGFzLmZhY3RvcigiQ2l1dGF0IFZlbGxhIiksIFRSVUUgfiBhcy5mYWN0b3Ioc2VjdG9yKSksCiAgICAgICAgIG1vbnRoID0gY2FzZV93aGVuKG1vbnRoID09IDEgfiBhcy5pbnRlZ2VyKDEzKSwgVFJVRSB+IGFzLmludGVnZXIobW9udGgpKSkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZGF5LCBtb250aCwgeWVhciwgaG91cikKICBkYXRhCn0KYGBgCgpBZ2dyZWdhdGUgZGF0YToKYGBge3J9CmRhdGFfMDZfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wNl9KdW55X3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8wN18yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzA3X0p1bGlvbF9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMDhfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wOF9BZ29zdF9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMDlfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wOV9TZXRlbWJyZV9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMTBfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8xMF9PY3R1YnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8xMl8yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzEyX0Rlc2VtYnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8xMV8yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzExX25vdmVtYnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8wMV8yMDE5IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE5XzAxX0dlbmVyX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YSA8LSByYmluZChkYXRhXzA2XzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8wN18yMDE4LAogICAgICAgICAgICAgIGRhdGFfMDhfMjAxOCwKICAgICAgICAgICAgICBkYXRhXzA5XzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8xMF8yMDE4LAogICAgICAgICAgICAgIGRhdGFfMTFfMjAxOCwKICAgICAgICAgICAgICBkYXRhXzEyXzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8wMV8yMDE5KSAlPiUgY2xlYW5fYmNuX2RhdGEoKSAKc3VtbWFyeShkYXRhKQpgYGAKCmBgYHtyfQpwbG90aXQgPC0gZGF0YSAlPiUgCiAgZ2F0aGVyKG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHZhbG9yX28zLCB2YWxvcl9ubzIsIHZhbG9yX3BtMTApICU+JQogIGZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYsIHNlY3RvciAlaW4lIGMoIkVpeGFtcGxlIiwgIlBhbGF1IFJlaWFsIiwgIlZhbGwgSGVicm9uIikpICU+JQogIHNlbGVjdChtb250aCwgZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogIGdyb3VwX2J5KG1vbnRoLCBob3VyLCBtZWFzdXJlLCBzZWN0b3IpICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbF9ob3VyID0gbWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKGhvdXIsIG1lYW5fdmFsX2hvdXIsIGNvbG9yID0gbWVhc3VyZSkpICsKICBsYWJzKHRpdGxlID0gIsK1Zy9twrMgbWVkaW8gZGUgY29udGFtaW5hZG9yZXMiLAogICAgICAgeCA9ICJIb3JhIiwgCiAgICAgICB5ID0gIsK1Zy9twrMgbWVkaW8iLAogICAgICAgY29sb3IgPSAiQ29udGFtaW5hZG9yIiwKICAgICAgIGNhcHRpb24gPSAiRGF0b3MgZGUgb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGxhYmVscyA9IGMoIk5PMiIsICJPMyIsICJQTTEwIikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfZ3JpZChzZWN0b3IgfiBtb250aCkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCmBgYHtyfQooaiA8LSBkYXRhICU+JSAKICBnYXRoZXIobWVhc3VyZSwgbWVhc3VyZV92YWx1ZSwgdmFsb3JfbzMsIHZhbG9yX25vMiwgdmFsb3JfcG0xMCkgJT4lCiAgI2ZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYsIHNlY3RvciAlaW4lIGMoIkVpeGFtcGxlIiwgIlBhbGF1IFJlaWFsIiwgIlZhbGwgSGVicm9uIikpICU+JQogIGZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYpICU+JQogIHNlbGVjdChtb250aCwgZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogICBtdXRhdGUobWVhc3VyZSA9IGNhc2Vfd2hlbihtZWFzdXJlID09ICJ2YWxvcl9ubzIiIH4gIk5PMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX28zIiB+ICJPMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX3BtMTAiIH4gIlBNMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gbWVhc3VyZSkpICU+JQogIGdyb3VwX2J5KG1vbnRoLCBtZWFzdXJlLCBzZWN0b3IpICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbF9tb250aCA9IG1lYW4obWVhc3VyZV92YWx1ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyhtb250aCwgbWVhbl92YWxfbW9udGgpKSArCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IGF2ZXJhZ2Ugb2YgcG9sbHV0YW50cyBjb2xvcmVkIGJ5IGRpc3RyaWN0LCBKdW5lIDIwMTggLSBKYW4gMjAxOSIsCiAgICAgICB4ID0gIk1vbnRoIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiRGlzdHJpY3QiLAogICAgICAgY2FwdGlvbiA9ICJEYXRhIGZyb20gb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogICNzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSwgYWVzKGNvbG9yID0gc2VjdG9yKSkgKwogIGdlb21fc21vb3RoKHNlPUZBTFNFLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBtZXRob2Q9bG0pICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IG1lYXN1cmUsIG5jb2wgPSAzKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjZTQxYTFjIiwiIzM3N2ViOCIsIiM0ZGFmNGEiLCIjOTg0ZWEzIiwiI2ZmN2YwMCIsIiM5OTk5OTkiLCIjYTY1NjI4IiwiI2Y3ODFiZiIpKSArCiAgdGhlbWVfbWluZSgpKQoKI21ldGhvZD1sbSBmb3IgZ2VvbV9zbW9vdGgKYGBgCmBgYHtyfQpnZ3Bsb3RseShqKSAKYGBgCmBgYHtyfQpzYXZlV2lkZ2V0KGdncGxvdGx5KGosIGR5bmFtaWNUaWNrcyA9IFRSVUUpLCBmaWxlID0gIm1lYW5ieW1vbnRoMjAxOC5odG1sIikKYGBgCgoKYGBge3J9CmRhdGEgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICAjZmlsdGVyKHllYXIgPj0gMjAxOCwgbW9udGggPj0gNiwgc2VjdG9yICVpbiUgYygiRWl4YW1wbGUiLCAiUGFsYXUgUmVpYWwiLCAiVmFsbCBIZWJyb24iKSkgJT4lCiAgZmlsdGVyKHllYXIgPj0gMjAxOCwgbW9udGggPj0gNikgJT4lCiAgc2VsZWN0KG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHNlY3RvcikgJT4lCiAgZ3JvdXBfYnkobW9udGgsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKG1lYW5fdmFsX21vbnRoID0gbWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKG1vbnRoLCBtZWFuX3ZhbF9tb250aCwgY29sb3IgPSBtZWFzdXJlKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIk1lcyIsIAogICAgICAgeSA9ICLCtWcvbcKzIG1lZGlvIiwKICAgICAgIGNvbG9yID0gIkNvbnRhbWluYWRvciIsCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIGRlIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSkgKwogICNnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH4gc2VjdG9yLCBuY29sID0gNCkgKwogIHRoZW1lX21pbmUoKQpgYGAKCmBgYHtyfQoocGxvdGl0IDwtIGRhdGEgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICBmaWx0ZXIoeWVhciA+PSAyMDE4LCBtb250aCA+PSA2LCBzZWN0b3IgJWluJSBjKCJFaXhhbXBsZSIsICJQYWxhdSBSZWlhbCIsICJWYWxsIEhlYnJvbiIpKSAlPiUKICBzZWxlY3QobW9udGgsIGRheSwgaG91ciwgbWVhc3VyZSwgbWVhc3VyZV92YWx1ZSwgc2VjdG9yKSAlPiUKICBncm91cF9ieShtb250aCwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWxfbW9udGggPSBtZWFuKG1lYXN1cmVfdmFsdWUsIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMobW9udGgsIG1lYW5fdmFsX21vbnRoKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIk1lcyIsIAogICAgICAgeSA9ICLCtWcvbcKzIG1lZGlvIiwKICAgICAgIGNhcHRpb24gPSAiRGF0b3MgZGUgb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH4gc2VjdG9yLCBucm93ID0gNCkgKwogIHRoZW1lX21pbmUoKSkKYGBgCgpgYGB7cn0KbGlicmFyeShwbG90bHkpCmxpYnJhcnkoaHRtbHdpZGdldHMpCiNzYXZlV2lkZ2V0KGdncGxvdGx5KHBsb3RpdCwgZHluYW1pY1RpY2tzID0gRkFMU0UpLCBmaWxlID0gIm1lYW5jb250Lmh0bWwiKTsKYGBgCgojIyMgSnVzdCBjbGVhbgpgYGB7cn0KY2xlYW5fZGF0YSA8LSBmdW5jdGlvbihkYXRhKSB7CiAgZGF0YSA8LSBkYXRhICU+JSAKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKHN0cl9leHRyYWN0KG5vbV9jYWJpbmEsICIoPzw9Wy1dXFxEKS4qIikpLAogICAgICAgICBxdWFsaXRhdF9haXJlID0gYXMuZmFjdG9yKHF1YWxpdGF0X2FpcmUpLAogICAgICAgICBxdWFsaXRhdF9vMyA9IGFzLmZhY3RvcihxdWFsaXRhdF9vMyksCiAgICAgICAgIHZhbG9yX28zID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9vMywgIl5bWzpkaWdpdDpdXSIpKSwKICAgICAgICAgcXVhbGl0YXRfbm8yID0gYXMuZmFjdG9yKHF1YWxpdGF0X25vMiksCiAgICAgICAgIHZhbG9yX25vMiA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodmFsb3Jfbm8yLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9wbTEwID0gYXMuZmFjdG9yKHF1YWxpdGF0X3BtMTApLAogICAgICAgICB2YWxvcl9wbTEwID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9wbTEwLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBkYXRlID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIi4qW1s6c3BhY2U6XV0iKSwKICAgICAgICAgaG91ciA9IHN0cl9leHRyYWN0KGdlbmVyYXQsICIoPzw9W1s6c3BhY2U6XV0pWzAtOS5dKyIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBkYXRlLCBpbnRvID0gYygiZGF5IiwgIm1vbnRoIiwgInllYXIiKSwgc2VwID0gIi8iKSAlPiUKICBtdXRhdGUoZGF5ID0gYXMuaW50ZWdlcihkYXkpLAogICAgICAgICBtb250aCA9IGFzLmludGVnZXIobW9udGgpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICAgICAgICAgaG91ciA9IGFzLmludGVnZXIoaG91ciksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihtb250aCkpICU+JQogIHNlbGVjdChzZWN0b3IsIHF1YWxpdGF0X2FpcmUsIHF1YWxpdGF0X28zLCB2YWxvcl9vMywgcXVhbGl0YXRfbm8yLCB2YWxvcl9ubzIsIHF1YWxpdGF0X3BtMTAsCiAgICAgICAgIHZhbG9yX3BtMTAsIGRheSwgbW9udGgsIHllYXIsIGhvdXIpCiAgZGF0YQp9CmBgYAoKYGBge3J9CihwIDwtIGRhdGFfMDFfMjAxOSAlPiUgY2xlYW5fZGF0YSgpICU+JQogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDE5LCBtb250aCA9PSAxKSAlPiUKICBzZWxlY3QoZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogICBtdXRhdGUobWVhc3VyZSA9IGNhc2Vfd2hlbihtZWFzdXJlID09ICJ2YWxvcl9ubzIiIH4gIk5PMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX28zIiB+ICJPMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX3BtMTAiIH4gIlBNMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gbWVhc3VyZSkpICU+JQogIGdyb3VwX2J5KGhvdXIsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKGF2Z19ob3VyID0gYXMubnVtZXJpYyhmb3JtYXQocm91bmQobWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBkaWdpdHMgPSAyKSwgbnNtYWxsID0gMikpKSAlPiUKICAgCiAgIAogICAKICBnZ3Bsb3QoYWVzKGhvdXIsIGF2Z19ob3VyLCBjb2xvciA9IG1lYXN1cmUpKSArCiAgbGFicyh0aXRsZSA9ICJNZWFuIHZhbHVlIG9mIHBvbGx1dGFudHMgYnkgaG91ciBpbiBKYW51YXJ5IDIwMTkiLAogICAgICAgeCA9ICJIb3VyIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiUG9sbHV0YW50IiwKICAgICAgIGNhcHRpb24gPSAiRGF0YSBmcm9tIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICAjc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogIGdlb21fbGluZShzaXplPTEpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbnJvdyA9IDIpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNlNDFhMWMiLCIjMzc3ZWI4IiwiIzRkYWY0YSIpKSArCiAgdGhlbWVfbWluZSgpCiAgKQpgYGAKCmBgYHtyfQpzYXZlV2lkZ2V0KGdncGxvdGx5KHAsIGR5bmFtaWNUaWNrcyA9IFRSVUUpLCBmaWxlID0gIm1lYW5qYW4uaHRtbCIpCmBgYAoKYGBge3J9CmdncGxvdGx5KHApIAoKYGBgCgoKCgoKCgoKCgoKCgoKCgojIyMgTW9ydGFsaXRhdApgYGB7cn0KbW9ydGFsaXRhdCA8LSB0YmxfZGYoZnJlYWQoIjIwMThfdGF4YV9tb3J0YWxpdGF0LmNzdiIsIGhlYWRlcj1UUlVFKSkKbW9ydGFsaXRhdCAlPiUKICBzZWxlY3QoTm9tX2Rpc3RyaWN0ZSwgTm9tX2JhcnJpLCBOb21icmUpICU+JQogIGdyb3VwX2J5KE5vbV9kaXN0cmljdGUpICU+JQogIHN1bW1hcmlzZShtZWFuX24gPSBtZWFuKE5vbWJyZSkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX2JhcihhZXMoeCA9IE5vbV9kaXN0cmljdGUsIHkgPSBtZWFuX24pLHN0YXQgPSAiaWRlbnRpdHkiKQpgYGAKCgpgYGB7cn0KdGhlbWVfbWluZSA8LSBmdW5jdGlvbiAoKSB7IAogICAgdGhlbWVfYncoYmFzZV9zaXplPTEyLCBiYXNlX2ZhbWlseT0iSGVsdmV0aWNhIikgJStyZXBsYWNlJSAKICAgICAgICB0aGVtZSgKICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpCiAgICAgICAgKQp9CmBgYAoKCmBgYHtyfQpkYXRhXzA2XzIwMTkgPC0gdGJsX2RmKGZyZWFkKCJkYXRhLzIwMTlfMDZfanVueV9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMDRfMjAxOSA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOV8wNF9BYnJpbF9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCiNzdW1tYXJ5KGRhdGFfMDZfMjAxOSkKYGBgCgoKYGBge3J9Cmxlbmd0aChuYW1lcyhkYXRhXzA2XzIwMTkpKQooaSA8LSBkYXRhXzA2XzIwMTkgJT4lCiAgc2VsZWN0KDU6NTcpICU+JQogIG11dGF0ZShtZWFzdXJlID0gYXMuZmFjdG9yKGNhc2Vfd2hlbihDT0RJX0NPTlRBTUlOQU5UID09IDEgfiAiU08yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA3IH4gIk5PIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA4IH4gIk5PMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPRElfQ09OVEFNSU5BTlQgPT0gMTIgfiAiTk94IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxNCB+ICJPMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPRElfQ09OVEFNSU5BTlQgPT0gNiB+ICJDTyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPRElfQ09OVEFNSU5BTlQgPT0gMTAgfiAiUE0xMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiIikpKSAlPiUKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKGNhc2Vfd2hlbihFU1RBQ0lPID09IDQgfiAiUG9ibGVub3UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQyIH4gIlNhbnRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0MyB+ICJFaXhhbXBsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDQgfiAiR3LDoGNpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTAgfiAiQ2l1dGFkZWxsYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTQgfiAiVmFsbCBIZWJyb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDU3IH4gIlBhbGF1IFJlaWFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIGdhdGhlcihob3VyLCBtZWFzdXJlX3ZhbHVlLCBzdGFydHNfd2l0aCgiSCIpKSAlPiUKICBnYXRoZXIodmFsaWRhdGlvbiwgdmFsLCBzdGFydHNfd2l0aCgiViIpKSAlPiUgZGlzdGluY3QoKSAlPiUKICBtdXRhdGUoZGF5ID0gYXMuaW50ZWdlcihESUEpLAogICAgICAgICBtb250aCA9IGFzLmludGVnZXIoTUVTKSwKICAgICAgICAgeWVhciA9IGFzLmludGVnZXIoQU5ZKSwKICAgICAgICAgaG91ciA9IGFzLmludGVnZXIoc3RyX2V4dHJhY3QoaG91ciwiLi4kIikpKSAlPiUKICBzZWxlY3Qoc2VjdG9yLCB5ZWFyLCBtb250aCwgZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlKSAlPiUKICAjZmlsdGVyKHNlY3RvciA9PSAiQ2l1dGFkZWxsYSIpICU+JQogIGdyb3VwX2J5KGhvdXIsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKGF2Z19ob3VyID0gYXMubnVtZXJpYyhmb3JtYXQocm91bmQobWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBkaWdpdHMgPSAyKSwgbnNtYWxsID0gMikpKSAlPiUKICAgIAogIGdncGxvdChhZXMoaG91ciwgYXZnX2hvdXIsIGNvbG9yID0gbWVhc3VyZSkpICsKICBsYWJzKHRpdGxlID0gIk1lYW4gdmFsdWUgb2YgcG9sbHV0YW50cyBieSBob3VyIGluIEp1bmUgMjAxOSIsCiAgICAgICB4ID0gIkhvdXIiLCAKICAgICAgIHkgPSAiwrVnL23CsyIsCiAgICAgICBjb2xvciA9ICJQb2xsdXRhbnQiLAogICAgICAgY2FwdGlvbiA9ICJEYXRhIGZyb20gb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogICNzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgI3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJwdXJwbGUiLCAieWVsbG93IiwgInJlZCIsICJvcmFuZ2UiLCAiZ3JlZW4iLCAiYmx1ZSIsICJwaW5rIikpICsKICBnZW9tX2xpbmUoc2l6ZT0xKSArCiAgI2dlb21faGxpbmUoeWludGVyY2VwdCA9IDkwLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gInJlZCIpICsKICAjZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTEwLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gImdyZWVuIikgKwogICNnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyMDAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAicGluayIpICsKICAjZ2VvbV90ZXh0KGFlcygwLDkwLGxhYmVsID0gIkxpbWl0IE5PMiBieSBoIiwgdmp1c3QgPSAtMSksIGNvbG9yID0gImJsYWNrIikgKwogICNnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyMikpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbnJvdyA9IDEpICsKICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiI2U0MWExYyIsIiMzNzdlYjgiLCIjNGRhZjRhIiwiIzk4NGVhMyIsIiNmZjdmMDAiLCIjOTk5OTk5IiwiI2E2NTYyOCIpKSArCiAgdGhlbWVfbWluZSgpKQoKICAKYGBgCgpgYGB7cn0KZ2dwbG90bHkoaSkgCmBgYApgYGB7cn0Kc2F2ZVdpZGdldChnZ3Bsb3RseShpLCBkeW5hbWljVGlja3MgPSBUUlVFKSwgZmlsZSA9ICJtZWFuanVuMTkuaHRtbCIpCmBgYAoKCmBgYHtyfQphcHJpbDE5IDwtIGRhdGFfMDRfMjAxOSAlPiUKICBzZWxlY3QoNTo1NykgJT4lCiAgbXV0YXRlKG1lYXN1cmUgPSBhcy5mYWN0b3IoY2FzZV93aGVuKENPRElfQ09OVEFNSU5BTlQgPT0gMSB+ICJTTzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDcgfiAiTk8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDggfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMiB+ICJOT3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDE0IH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA2IH4gIkNPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMCB+ICJQTTEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3IoY2FzZV93aGVuKEVTVEFDSU8gPT0gNCB+ICJQb2JsZW5vdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDIgfiAiU2FudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQzIH4gIkVpeGFtcGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0NCB+ICJHcsOgY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1MCB+ICJDaXV0YWRlbGxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1NCB+ICJWYWxsIEhlYnJvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTcgfiAiUGFsYXUgUmVpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSkgJT4lCiAgZ2F0aGVyKGhvdXIsIG1lYXN1cmVfdmFsdWUsIHN0YXJ0c193aXRoKCJIIikpICU+JQogIGdhdGhlcih2YWxpZGF0aW9uLCB2YWwsIHN0YXJ0c193aXRoKCJWIikpICU+JSBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKERJQSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihNRVMpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcihBTlkpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdChob3VyLCIuLiQiKSkpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUpCgoKanVuZTE5IDwtIGRhdGFfMDZfMjAxOSAlPiUKICBzZWxlY3QoNTo1NykgJT4lCiAgbXV0YXRlKG1lYXN1cmUgPSBhcy5mYWN0b3IoY2FzZV93aGVuKENPRElfQ09OVEFNSU5BTlQgPT0gMSB+ICJTTzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDcgfiAiTk8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDggfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMiB+ICJOT3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDE0IH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA2IH4gIkNPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMCB+ICJQTTEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3IoY2FzZV93aGVuKEVTVEFDSU8gPT0gNCB+ICJQb2JsZW5vdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDIgfiAiU2FudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQzIH4gIkVpeGFtcGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0NCB+ICJHcsOgY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1MCB+ICJDaXV0YWRlbGxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1NCB+ICJWYWxsIEhlYnJvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTcgfiAiUGFsYXUgUmVpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSkgJT4lCiAgZ2F0aGVyKGhvdXIsIG1lYXN1cmVfdmFsdWUsIHN0YXJ0c193aXRoKCJIIikpICU+JQogIGdhdGhlcih2YWxpZGF0aW9uLCB2YWwsIHN0YXJ0c193aXRoKCJWIikpICU+JSBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKERJQSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihNRVMpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcihBTlkpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdChob3VyLCIuLiQiKSkpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUpCgpkYXRhMTkgPC0gcmJpbmQoYXByaWwxOSwganVuZTE5KQpzdW1tYXJ5KGRhdGExOSkKYGBgCgpgYGB7cn0KKGsgPC0gZGF0YTE5ICU+JSAKICBmaWx0ZXIoeWVhciA+PSAyMDE5LCBtb250aCA+PSA0KSAlPiUKICBncm91cF9ieShtb250aCwgbWVhc3VyZSwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UoYXZnX21vbnRoID0gYXMubnVtZXJpYyhmb3JtYXQocm91bmQobWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBkaWdpdHMgPSAyKSwgbnNtYWxsID0gMikpKSAlPiUKICAjc2VsZWN0KG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHNlY3RvcikgJT4lCiAgZ2dwbG90KGFlcyhtb250aCwgYXZnX21vbnRoKSkgKwogIGxhYnModGl0bGUgPSAiTW9udGhseSBhdmVyYWdlIG9mIHBvbGx1dGFudHMgY29sb3JlZCBieSBkaXN0cmljdCwgQXByaWwgMjAxOSAtIEp1bmUgMjAxOSIsCiAgICAgICB4ID0gIk1vbnRoIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiRGlzdHJpY3QiLAogICAgICAgY2FwdGlvbiA9ICJEYXRhIGZyb20gb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogICNzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSwgYWVzKGNvbG9yID0gc2VjdG9yKSkgKwogICNnZW9tX3Ntb290aChzZT1GQUxTRSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbWV0aG9kPWxtKSArCiAgI2dlb21fcG9pbnQoKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDQsNikpICsKICBmYWNldF93cmFwKH4gbWVhc3VyZSwgbmNvbCA9IDcpICsKICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjZTQxYTFjIiwiIzM3N2ViOCIsIiM0ZGFmNGEiLCIjOTg0ZWEzIiwiI2ZmN2YwMCIsIiM5OTk5OTkiLCIjYTY1NjI4IikpICsKICB0aGVtZV9taW5lKCkpCgojbWV0aG9kPWxtIGZvciBnZW9tX3Ntb290aApgYGAKCmBgYHtyfQpnZ3Bsb3RseShrKSAKYGBgCgpgYGB7cn0Kc2F2ZVdpZGdldChnZ3Bsb3RseShrLCBkeW5hbWljVGlja3MgPSBUUlVFKSwgZmlsZSA9ICJtZWFuMTkuaHRtbCIpCmBgYAoKCmBgYHtyfQphY2NpZGVudHMxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF9hY2NpZGVudHNfY2F1c2VzX2d1X2Jjbi5jc3YiLGhlYWRlcj1UUlVFKSkKc3VtbWFyeShhY2NpZGVudHMxOCkKaGVhZChhY2NpZGVudHMxOCkKYGBgCmBgYHtyfQooYWM8LSBhY2NpZGVudHMxOCAlPiUgZmlsdGVyKE1lc19hbnkgPj0gNiwgQW55ID09IDIwMTgpICU+JQogIG11dGF0ZShzZWN0b3IgPSBjYXNlX3doZW4oTm9tX2Rpc3RyaWN0ZSA9PSAiRGVzY29uZWd1dCIgfiBhcy5jaGFyYWN0ZXIoTkEpLFRSVUUgfiBhcy5jaGFyYWN0ZXIoTm9tX2Rpc3RyaWN0ZSkpLAogICAgICAgICBzZWN0b3IgPSBhcy5mYWN0b3Ioc2VjdG9yKSwKICAgICAgICAgeWVhciA9IEFueSwKICAgICAgICAgbW9udGggPSBNZXNfYW55LAogICAgICAgICBkYXkgPSBEaWFfbWVzLAogICAgICAgICBob3VyID0gSG9yYV9kaWEpICU+JQogICBkcm9wX25hKCkgJT4lCiAgc2VsZWN0KHNlY3RvciwgeWVhciwgbW9udGgsIGRheSwgaG91cikpCmxldmVscyhhYyRzZWN0b3IpCmBgYAoKYGBge3J9CmFjICU+JQogIGdyb3VwX2J5KHNlY3RvciwgbW9udGgsIGhvdXIpICU+JQogIHN1bW1hcml6ZShpbmNpZGVudHMgPSBuKCkpICU+JQogIGdncGxvdChhZXMoeCA9IGhvdXIsIHkgPSBpbmNpZGVudHMsIGNvbG9yID0gZmFjdG9yKG1vbnRoKSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgc2l6ZSA9IDEsIGNvbG9yID0gImJsYWNrIikgKwogICNnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH4gc2VjdG9yLCBuY29sID0gNSkgKwogIHRoZW1lX21pbmltYWwoKQogIApgYGAKCgpgYGB7cn0KYWMgJT4lCiAgZ3JvdXBfYnkoc2VjdG9yLCBob3VyKSAlPiUKICBzdW1tYXJpemUoaW5jaWRlbnRzID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBob3VyLCB5ID0gaW5jaWRlbnRzLCBjb2xvciA9IHNlY3RvcikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgc2l6ZSA9IDEsIGNvbG9yID0gImJsYWNrIikgKwogICNnZW9tX3BvaW50KCkgKyAKICAjZmFjZXRfd3JhcCh+IHNlY3RvciwgbmNvbCA9IDUpICsKICB0aGVtZV9taW5pbWFsKCkKICAKYGBgCgpgYGB7cn0KYWMgJT4lCiAgZ3JvdXBfYnkoc2VjdG9yLCBtb250aCkgJT4lCiAgc3VtbWFyaXplKGluY2lkZW50cyA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbW9udGgsIHkgPSBpbmNpZGVudHMsIGNvbG9yID0gc2VjdG9yKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBzaXplID0gMSwgY29sb3IgPSAiYmxhY2siKSArCiAgI2dlb21fcG9pbnQoKSArIAogICNmYWNldF93cmFwKH4gc2VjdG9yLCBuY29sID0gNSkgKwogIHRoZW1lX21pbmltYWwoKQogIApgYGAKCgoKCg==